"""
main.py 系统GUI界面实现
"""
from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication
from pgtools.plugins.client.qtwidget_helper import TListWidget, TTreeWidget
from ui_message import Ui_MessageForm
from ui_category import Ui_CategoriesForm
from model import FormattedMessageCategory, FormattedMessage


class CategoriesForm(QWidget):
    """
    基于QWidget的子类。
    实现了一个消息类别管理界面，用户可以通过界面进行刷新、添加、删除和更新消息类别。
    """
    closed = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_CategoriesForm()
        self.ui.setupUi(self)
        self.db = FormattedMessageCategory()
        self.list_widget = TListWidget(self.ui.listWidget)
        self.on_pushButton_refresh_pressed()

    def on_pushButton_refresh_pressed(self):
        """
        刷新按钮按下时的操作。
        清空列表，获取所有消息类别数据并设置到列表中。
        """
        self.list_widget.clear()
        tdata = self.db.get_all()
        if tdata:
            self.list_widget.set_db_data(tdata)
            self.ui.lineEdit.clear()

    def on_pushButton_add_pressed(self):
        """
        添加按钮按下时的操作。
        从输入框中获取类别名称，如果存在则添加到数据库中，并刷新界面。
        """
        n = self.ui.lineEdit.text().strip()
        if n:
            try:
                self.db.add_one(name=n)
                self.on_pushButton_refresh_pressed()
            except Exception as e:
                if 'UNIQUE constraint failed' in e.args[0]:
                    print('类别名已存在，添加失败')
                    QMessageBox.critical(
                        self, '错误',
                        '类别名已存在，添加失败!\n%s' % e.args[0])

    def on_pushButton_del_pressed(self):
        """
        删除按钮按下时的操作。
        获取当前选中的类别名称，检查该类别下是否有消息，如果没有则从数据库中删除该类别，并刷新界面。
        """
        if self.list_widget.has_selected():
            name = self.list_widget.get_current_text()
            if name:
                msg = FormattedMessage().get({'category': name})
                if not msg:  # 该类别下没有消息时才可以删除
                    self.db.delete({'name': name})
                    self.on_pushButton_refresh_pressed()

    def on_pushButton_update_pressed(self):
        """
        更新按钮按下时的操作。
        获取当前选中的类别名称和新的类别名称，如果新名称存在，则更新数据库中该类别的名称，并刷新界面。
        """
        if self.list_widget.has_selected():
            name = self.list_widget.get_current_text()
            new_name = self.ui.lineEdit.text().strip()
            if name and new_name:
                FormattedMessage().set({'category': name}, category=new_name)
                self.db.set({'name': name}, name=new_name)
                self.on_pushButton_refresh_pressed()

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        """
        关闭窗口时的操作。
        发出关闭信号并接受关闭事件。
        """
        self.closed.emit()
        a0.accept()


class MessageForm(QWidget):

    def __init__(self):
        super().__init__()
        self.ui = Ui_MessageForm()
        self.ui.setupUi(self)
        self.category_form = None
        self.fm = FormattedMessage()
        # 绑定便捷类
        self.msg_tree_widget = TTreeWidget(self.ui.treeWidget)
        # 注册单击处理函数
        self.msg_tree_widget.set_func_item_clicked(self.tree_clicked)
        self.get_format_msg()

    def tree_clicked(self, row, col, name):
        """
        事件处理函数，默认传入参数有三个：
        row：单击（或双击）的行标
        col：单击（或双击）的列标
        name：单击（或双击）的item的text值
        """
        fm = self.fm.get({'name': name})
        if fm:
            self.ui.lineEdit.setText(name)
            self.ui.textEdit.setPlainText(fm[0]['text'])
            self.ui.comboBox.setCurrentText(fm[0]['category'])
        else:
            self.ui.lineEdit.clear()
            self.ui.textEdit.clear()

    def get_format_msg(self):
        """将格式化消息类别和格式化消息数据按树形控件数据要求进行整理"""
        self.msg_tree_widget.clear()
        self.ui.comboBox.clear()
        self.ui.lineEdit.clear()
        self.ui.textEdit.clear()
        # 设置树形控件头部（顶部）标签
        self.msg_tree_widget.set_header('name')

        tree = []  # 以(id, name, pid)的形式保存数据
        tid = 1
        category_tid = {}  # 用于由category_name->tid的查找

        for c in FormattedMessageCategory().get_all():
            # 添加到下拉框
            self.ui.comboBox.addItem(c['name'])
            # 构造(id, name, pid)
            tree.append((tid, c['name'], 0))
            category_tid[c['name']] = tid
            tid += 1
        # 按照树形控件数据结构继续添加格式化消息
        for m in self.fm.get_all():
            # 使用m['category']为类别name
            # 利用category_name获取该类别tid，即为当前消息的pid
            tree.append((tid, m['name'], category_tid[m['category']]))
            tid += 1
        self.msg_tree_widget.set_data(tree)

    def on_pushButton_category_pressed(self):
        self.category_form = CategoriesForm(self)
        # 设置窗口类型为窗口
        self.category_form.setWindowFlag(QtCore.Qt.WindowType.Window)
        self.category_form.closed.connect(self.get_format_msg)
        self.category_form.show()

    def _get_ui_data(self) -> dict:
        """获取界面输入数据，并按数据库列转化为字典型数据"""
        name = self.ui.lineEdit.text().strip()
        text = self.ui.textEdit.toPlainText()
        category = self.ui.comboBox.currentText()
        if not name or not text or not category:
            return {}

        def _get_elementlist(text: str):
            """提取text中{}内的变量"""
            elementlist = []
            _text = text
            start = _text.find('{')  # 查找第一个{
            end = _text.find('}')  # 查找第一个}
            while 0 <= start <= end and _text:
                # 保存 {}之间的字符串
                elementlist.append(_text[start + 1:end])
                # 在剩下是字符串中继续寻找
                _text = _text[end + 1:]
                start = _text.find('{')
                end = _text.find('}')
            return elementlist

        return {'name': name, 'text': text,
                'elementlist': '|'.join(_get_elementlist(text)),
                'category': category}

    def on_pushButton_add_pressed(self):
        # 获取UI数据
        data = self._get_ui_data()
        if data:
            try:
                # 添加数据
                self.fm.add_one(**data)
                # 更新格式化消息
                self.get_format_msg()
            except Exception as e:
                if 'UNIQUE constraint failed' in e.args[0]:
                    print('消息名已存在，添加失败')
                    QMessageBox.critical(
                        self, '错误',
                        '消息名已存在，添加失败!\n%s' % e.args[0])

    def on_pushButton_update_pressed(self):
        # 判断是否有选中项
        if self.msg_tree_widget.has_selected():
            # 获取当前选中项的文本
            current = self.msg_tree_widget.get_current_text()
            if current:
                # 更新数据
                self.fm.set({'name': current}, **self._get_ui_data())
                # 更新格式化消息
                self.get_format_msg()

    def on_pushButton_del_pressed(self):
        # 判断是否有选中项
        if self.msg_tree_widget.has_selected():
            # 获取当前选中项的文本
            current = self.msg_tree_widget.get_current_text()
            if current:
                # 删除数据
                self.fm.delete({'name': current})
                # 更新格式化消息
                self.get_format_msg()


if __name__ == '__main__':
    app = QApplication([])
    w = MessageForm()
    w.show()
    app.exec_()
